﻿using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace YanZhiwei.DotNet2.Utilities.Base
{
    /// <summary>
    /// Queue线程安全实现的帮助类
    /// 说明
    /// 默认读锁超时1000毫秒
    /// 默认写锁超时1000毫秒
    /// </summary>
    /// <typeparam name="T">泛型</typeparam>
    public class ThreadSafeQueue<T>
    {
        /* 参考资料
         * 参考：
         * 1. http://www.codeproject.com/Articles/38908/Thread-Safe-Generic-Queue-Class
         * 2. http://stackoverflow.com/questions/13416889/thread-safe-queue-enqueue-dequeue
         * 3. http://blogs.msdn.com/b/jaredpar/archive/2009/02/16/a-more-usable-thread-safe-collection.aspx
         */
        #region 构造函数以及变量
        private readonly Queue<T> QueueTF;
        private readonly ReaderWriterLock rwlock = new ReaderWriterLock();
        static int readerTimeout = 1000;//默认读锁超时1000毫秒
        static int writerTimeout = 1000;//默认写锁超时1000毫秒
        /// <summary>
        /// 默认构造函数
        /// </summary>
        public ThreadSafeQueue()
        {
            QueueTF = new Queue<T>();
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="capacity">初始容量</param>
        public ThreadSafeQueue(int capacity)
        {
            QueueTF = new Queue<T>(capacity);
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="collection">IEnumerable</param>
        public ThreadSafeQueue(IEnumerable<T> collection)
        {
            QueueTF = new Queue<T>(collection);
        }
        #endregion 
        #region GetEnumerator【线程安全】
        /// <summary>
        /// GetEnumerator【线程安全】
        /// </summary>
        /// <returns>IEnumerator</returns>
        public IEnumerator<T> GetEnumerator()
        {
            Queue<T> _tmpQueue;
            rwlock.AcquireReaderLock(readerTimeout);
            try
            {
                _tmpQueue = new Queue<T>(QueueTF);
            }
            finally
            {
                rwlock.ReleaseReaderLock();
            }
            foreach (T item in _tmpQueue)
                yield return item;
        }
        #endregion 
        #region  Enqueue【线程安全】
        /// <summary>
        /// Enqueue【线程安全】
        /// </summary>
        /// <param name="item">泛型</param>
        public void Enqueue(T item)
        {
            rwlock.UpgradeToWriterLock(writerTimeout);
            try
            {
                QueueTF.Enqueue(item);
            }
            finally
            {
                rwlock.ReleaseWriterLock();
            }
        }
        #endregion 
        #region Dequeue【线程安全】
        /// <summary>
        /// Dequeue【线程安全】
        /// </summary>
        /// <returns>泛型</returns>
        public T Dequeue()
        {
            rwlock.AcquireReaderLock(readerTimeout);
            try
            {
                return QueueTF.Dequeue();
            }
            finally
            {
                rwlock.ReleaseReaderLock();
            }
        }
        #endregion 
        #region EnqueueAll【线程安全】
        /// <summary>
        /// EnqueueAll【线程安全】
        /// </summary>
        /// <param name="ItemsToQueue">IEnumerable</param>
        public void EnqueueAll(IEnumerable<T> ItemsToQueue)
        {
            rwlock.UpgradeToWriterLock(writerTimeout);
            try
            {
                foreach (T item in ItemsToQueue)
                    QueueTF.Enqueue(item);
            }
            finally
            {
                rwlock.ReleaseWriterLock();
            }
        }
        #endregion 
        #region EnqueueAll【线程安全】
        /// <summary>
        /// EnqueueAll【线程安全】
        /// </summary>
        /// <param name="ItemsToQueue">IList</param>
        public void EnqueueAll(IList<T> ItemsToQueue)
        {
            rwlock.UpgradeToWriterLock(writerTimeout);
            try
            {
                foreach (T item in ItemsToQueue)
                    QueueTF.Enqueue(item);
            }
            finally
            {
                rwlock.ReleaseWriterLock();
            }
        }
        #endregion 
        #region  DequeueAll【线程安全】
        /// <summary>
        /// DequeueAll【线程安全】
        /// </summary>
        /// <returns>IList</returns>
        public IList<T> DequeueAll()
        {
            rwlock.AcquireReaderLock(readerTimeout);
            try
            {
                IList<T> returnList = new List<T>();
                while (QueueTF.Count > 0)
                    returnList.Add(QueueTF.Dequeue());
                return returnList;
            }
            finally
            {
                rwlock.ReleaseReaderLock();
            }
        }
        #endregion 
        #region Count 【线程安全】
        /// <summary>
        /// Count 【线程安全】
        /// </summary>
        /// <returns></returns>
        public int Count()
        {
            rwlock.AcquireReaderLock(readerTimeout);
            try
            {
                return QueueTF.Count;
            }
            finally
            {
                rwlock.ReleaseReaderLock();
            }
        }
        #endregion 
    }
}